package com.hyper_yang._04_jvm.chap06;

import java.lang.ref.SoftReference;

/**
 * 软引用：在触发GC时，暂时不回收这个对象，先回收其他垃圾对象，如果空间够用，那么这个软引用对象就躲过这次GC。如果空间依然不够，那么即使存在软引用，那么对象也必须被回收。
 */
//-Xms10m -Xmx10m
public class SoftReferenceTest {

    public static void main(String[] args) {
        //创建对象，建立软引用
        SoftReference<User> userSoftRef = new SoftReference<>(new User(1, "zhangsan"));

        //上面的一行代码，等价于如下的二行代码
        //User u1 = new User(1,"zhangsan");
        //SoftReference<User> userSoftRef = new SoftReference<>(u1);

        //u1 = null;//如果之前定义了强引用，则需要取消强引用，否则后期userSoftRef无法回收

        //从软引用中获得强引用对象
        System.out.println(userSoftRef.get());

        //内存不足测试：让系统认为内存资源紧张
        //测试环境： -Xms10m -Xmx10m
        try {
            //默认新生代占堆的1/3空间，老年代占堆的2/3空间，因此7m的内容在哪个空间都放不下
            byte[] b = new byte[1024 * 1024 * 7]; //7M
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {

            System.out.println("finally");

            //再次从软引用中获取数据
            //在报OOM之前，垃圾回收器会回收软引用的可达对象。
            System.out.println(userSoftRef.get());

            System.out.print("最大堆大小：Xmx=");
            System.out.println(Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M");

            System.out.print("剩余堆大小：free mem=");
            System.out.println(Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M");

            System.out.print("当前堆大小：total mem=");
            System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");
        }
    }
}